home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d (not only polygonal) solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Aug. 1990 *
- ******************************************************************************
- * Module to interplate internal vertices using vertices on the given *
- * convex boundary OriginalVList. All internal vertices are assumed to be in *
- * the interior of the convex region defined by OriginalVList or on its *
- * boundary. *
- *****************************************************************************/
-
- #include <math.h>
- #include "irit_sm.h"
- #include "iritprsr.h"
- #include "geomat3d.h"
- #include "intrnrml.h"
-
- /* #define DEBUG1 To define polygon (with normals printing routine. */
-
- static void UpdateOneVertexNormal(IPVertexStruct *VUpdate,
- IPPolygonStruct *OriginalPl);
-
- #ifdef DEBUG1
- static void PrintPolygon(IPPolygonStruct *Pl);
- #endif /* DEBUG1 */
-
- /*****************************************************************************
- * For each polygon in PlList update any vertex normal which is zero to an *
- *interpolated value using the Original polygon vertex list OriginalVList. *
- * All the new vertices are enclosed within the original polygon which *
- * must be convex as well. *
- *****************************************************************************/
- void UpdateVerticesNormals(IPPolygonStruct *PlList, IPPolygonStruct *OriginalPl)
- {
- IPVertexStruct *V, *VHead;
-
- while (PlList) {
- V = VHead = PlList -> PVertex;
- do {
- if (APX_EQ(V -> Normal[0], 0.0) &&
- APX_EQ(V -> Normal[1], 0.0) &&
- APX_EQ(V -> Normal[2], 0.0)) {
- /* This vertex need to be updated. */
- UpdateOneVertexNormal(V, OriginalPl);
- }
-
- V = V -> Pnext;
- }
- while (V != NULL && V != VHead);
-
- PlList = PlList -> Pnext;
- }
- }
-
- /*****************************************************************************
- * Update one vertex normal be a convex blend of boundary vertices normals *
- *****************************************************************************/
- static void UpdateOneVertexNormal(IPVertexStruct *VUpdate,
- IPPolygonStruct *OriginalPl)
- {
- IPVertexStruct *V,
- *OriginalVList = OriginalPl -> PVertex;
-
- V = OriginalVList;
- do {
- if (Colinear3Vertices(V, VUpdate, V -> Pnext)) {
- /* Interpolate the normal according to the edge vertices VUpdate */
- /* is on and according to the distance of VUpdate to edge ends. */
- InterpNrmlBetweenTwo(VUpdate, V, V -> Pnext);
- return;
- }
- V = V -> Pnext;
- }
- while (V != NULL && V != OriginalVList);
-
- /* If we are here then the point is not on the polygon boundary and in */
- /* that case we simply use the polygon normal as an approximation. */
- PT_COPY(VUpdate -> Normal, OriginalPl -> Plane);
- }
-
- /*****************************************************************************
- * Returns TRUE iff the 3 vertices are colinear. *
- *****************************************************************************/
- int Colinear3Vertices(IPVertexStruct *V1, IPVertexStruct *V2,
- IPVertexStruct *V3)
- {
- RealType l;
- VectorType V12, V23, V;
-
- if (PT_APX_EQ(V1 -> Coord, V2 -> Coord) ||
- PT_APX_EQ(V2 -> Coord, V3 -> Coord))
- return TRUE;
-
- PT_SUB(V12, V1 -> Coord, V2 -> Coord);
- PT_SUB(V23, V2 -> Coord, V3 -> Coord);
-
- /* Make sure the middle point is in fact in the middle. */
- if (V12[0] * V23[0] < -EPSILON ||
- V12[1] * V23[1] < -EPSILON ||
- V12[2] * V23[2] < -EPSILON)
- return FALSE;
-
- GMVecCrossProd(V, V12, V23);
-
- l = PT_LENGTH(V);
-
- return APX_EQ(l, 0.0);
- }
-
- /*****************************************************************************
- * Update Normal of the middle vertex V, assumed to be between V1 and V2. *
- *****************************************************************************/
- void InterpNrmlBetweenTwo(IPVertexStruct *V, IPVertexStruct *V1,
- IPVertexStruct *V2)
- {
- RealType t1, t2;
- VectorType Vec1, Vec2;
-
- PT_SUB(Vec1, V -> Coord, V1 -> Coord);
- PT_SUB(Vec2, V -> Coord, V2 -> Coord);
- t1 = PT_LENGTH(Vec1);
- t2 = PT_LENGTH(Vec2);
-
- PT_COPY(Vec1, V1 -> Normal);
- PT_COPY(Vec2, V2 -> Normal);
- PT_SCALE(Vec1, t2);
- PT_SCALE(Vec2, t1);
- PT_ADD(V -> Normal, Vec1, Vec2);
-
- PT_NORMALIZE(V -> Normal);
- }
-
- /*****************************************************************************
- * Copute Normal from middle position of Pt Between V1 and V2. *
- *****************************************************************************/
- void InterpNrmlBetweenTwo2(PointType Pt, VectorType Normal,
- IPVertexStruct *V1, IPVertexStruct *V2)
- {
- RealType t1, t2;
- VectorType Vec1, Vec2;
-
- PT_SUB(Vec1, Pt, V1 -> Coord);
- PT_SUB(Vec2, Pt, V2 -> Coord);
- t1 = PT_LENGTH(Vec1);
- t2 = PT_LENGTH(Vec2);
-
- PT_COPY(Vec1, V1 -> Normal);
- PT_COPY(Vec2, V2 -> Normal);
- PT_SCALE(Vec1, t2);
- PT_SCALE(Vec2, t1);
- PT_ADD(Normal, Vec1, Vec2);
-
- PT_NORMALIZE(Normal);
- }
-
- #ifdef DEBUG1
-
- /*****************************************************************************
- * Print the content of the given polygon, to standard output. *
- *****************************************************************************/
- static void PrintPolygon(IPPolygonStruct *Pl)
- {
- IPVertexStruct *V = Pl -> Coord,
- *VHead = V;
-
- do {
- printf(" %10lg %10lg %10lg (%10lg %10lg %10lg)",
- V -> Coord[0], V -> Coord[1], V -> Coord[2],
- V -> Normal[0], V -> Normal[1], V -> Normal[2]);
- if (IS_INTERNAL_EDGE(V))
- printf(" (Internal)\n");
- else
- printf("\n");
- V = V -> Pnext;
- }
- while (V!= NULL && V != VHead);
- }
-
- #endif /* DEBUG1 */
-